package com.linkdood.app.service.impl;

import com.linkdood.app.constants.ErrorCode;
import com.linkdood.app.exception.GeneralException;
import com.linkdood.app.exception.InvalidParamException;
import com.linkdood.app.service.VerifyCodeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.cache.CacheException;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service;

import java.util.Random;
import java.util.UUID;

/**
 * 验证码 service 类
 */
@Service
@Slf4j
public class VerifyCodeServiceImpl implements VerifyCodeService {
    private static final String VERIFY_CODE = "verifyCode";

    private final CacheManager cacheManager;

    public VerifyCodeServiceImpl(CacheManager cacheManager) {
        this.cacheManager = cacheManager;
    }

    /**
     * 发送验证码
     * @param phone 电话号码
     * @return 业务id
     */
    @Override
    public String sendCode(String phone) {
        if (StringUtils.isEmpty(phone)) {
            throw new GeneralException(ErrorCode.ERROR_PHONE_NOT_EMPTY);
        }
        return generateVerifyCode(phone);
    }

    /**
     * 校验验证码
     * @param bid 业务id
     * @param phone 电话号码
     * @param code 验证码
     */
    @Override
    public void checkVerifyCode(String bid, String phone, String code) {
        // FIXME 此处是测试时 使用的验证码，300352直接通过
        if (StringUtils.equals(code, "300352")) {
            return;
        }
        if (StringUtils.isBlank(bid)) {
            throw new InvalidParamException("bid");
        }
        // 获取验证码缓存
        String value = getCacheValue(bid);
        String[] arr = value.split("_");
        String phoneNum = arr[0];
        String phoneCode = arr[1];

        if (!StringUtils.equals(phoneNum, phone)) {
            throw new GeneralException(ErrorCode.ERROR_PHONE);
        }
        if (!StringUtils.equals(phoneCode, code)) {
            throw new GeneralException(ErrorCode.ERROR_VERIFY_CODE);
        }
    }

    /**
     * 获取验证码
     * @param bid 业务id
     * @return 验证码
     */
    @Override
    public String getCode(String bid) {
        // 获取验证码缓存
        String value = getCacheValue(bid);
        String result = "";
        if (StringUtils.isNotBlank(value)) {
            String[] arr = value.split("_");
            result = arr[1];
        }
        return result;
    }


    private String getCacheValue(String bid) {
        Cache cache = cacheManager.getCache(VerifyCodeServiceImpl.VERIFY_CODE);
        if (cache == null) {
            throw new CacheException("Not have cache for: " + VerifyCodeServiceImpl.VERIFY_CODE);
        }
        Cache.ValueWrapper valueWrapper = cache.get(bid);
        if (valueWrapper == null) {
            throw new GeneralException(ErrorCode.ERROR_VERIFY_CODE_EXPIRED);
        }
        Object obj = valueWrapper.get();
        if (obj == null || StringUtils.isBlank(obj.toString())) {
            throw new GeneralException(ErrorCode.ERROR_VERIFY_CODE_EXPIRED);
        }

        return obj.toString();
    }

    /**
     * 生成短信验证码
     *
     * @param phone 接受者手机号
     */
    @Override
    public String generateVerifyCode(String phone) {
        // 生成业务id
        String result = UUID.randomUUID().toString();
        // 生成6位验证码
        String phoneCode = String.valueOf(new Random().nextInt(899999) + 100000);
        // 放入缓存
        saveVerifyCodeToCache(result, phone, phoneCode);
        return result;
    }

    /**
     * 保存验证码到缓存
     * @param bid 业务id
     * @param phone 接收者手机号
     * @param phoneCode 验证码
     */
    @Override
    public void saveVerifyCodeToCache(String bid, String phone, String phoneCode) {
        Cache cache = cacheManager.getCache(VERIFY_CODE);
        if (cache == null) {
            throw new CacheException("Not have cache for: " + VERIFY_CODE);
        }
        String value = phone + "_" + phoneCode;
        log.info("验证码：{}", phoneCode);
        cache.put(bid, value);
        log.info("存入缓存为 key: {}, value: {}", bid, value);
    }
}
